package com.farmer.order.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.farmer.common.constants.Code;
import com.farmer.common.dto.OrderDTO;
import com.farmer.common.dto.ShopDTO;
import com.farmer.common.entity.Address;
import com.farmer.common.entity.Order;
import com.farmer.common.entity.PageResult;
import com.farmer.common.entity.ResModel;
import com.farmer.common.utils.NowDateUtils;
import com.farmer.order.client.ShopClient;
import com.farmer.order.client.UserClient;
import com.farmer.order.mapper.OrderMapper;
import com.farmer.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.farmer.common.constants.RedisConstants.ORDER_ID_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 林邵晨
 * @since 2023-03-06
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private ShopClient shopClient;

    @Resource
    private UserClient userClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 根据id查询订单详情
     * @param orderId
     * @return
     */
    @Override
    public ResModel getByOrderId(Integer orderId) {
        Order order = getById(orderId);
        OrderDTO orderDTO = BeanUtil.copyProperties(order, OrderDTO.class);
        orderDTO.setCreateTime(NowDateUtils.format(order.getCreateTime()));
        String shopIds = order.getShopIds();
        if (StrUtil.isNotEmpty(shopIds)){
            ArrayList<ShopDTO> list = new ArrayList<>();
            for (String s : shopIds.split(",")) {
                ShopDTO shopDTO = shopClient.getByShopId(Integer.parseInt(s));
                list.add(shopDTO);
            }
            orderDTO.setShop(list);
        }
        getAddressInfo(order, orderDTO);
        return ResModel.success(Code.SUCCESS,orderDTO);
    }

    private void getAddressInfo(Order order, OrderDTO orderDTO) {
        Integer addressId = order.getAddressId();
        Address address = userClient.getAddress(addressId);
        orderDTO.setAddress(address.getAddress() + address.getArea());
        orderDTO.setPhone(address.getPhone());
        orderDTO.setUsername(address.getUsername());

    }

    /**
     * 分页查询订单详情
     *
     * @param userId
     * @param current
     * @param size
     * @return
     */
    @Override
    public ResModel listByPage(Integer userId, Integer current, Integer size) {
        Page<Order> page = new Page<>(current, size);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(true,Order::getUserId,userId);
        wrapper.orderByDesc(true,Order::getCreateTime);
        Page<Order> selectPage = baseMapper.selectPage(page, wrapper);
        PageResult<OrderDTO> result = new PageResult<>();
        result.setCurrent(selectPage.getCurrent());
        result.setSize(selectPage.getSize());
        result.setTotal(selectPage.getTotal());
        ArrayList<OrderDTO> list = new ArrayList<>();
        for (Order order : selectPage.getRecords()) {
            OrderDTO orderDTO = BeanUtil.copyProperties(order, OrderDTO.class);
            orderDTO.setCreateTime(NowDateUtils.format(order.getCreateTime()));
            if (StrUtil.isNotEmpty(order.getShopIds())){
                ArrayList<ShopDTO> listDTO = new ArrayList<>();
                for (String s : order.getShopIds().split(",")) {
                    ShopDTO shopDTO = shopClient.getByShopId(Integer.parseInt(s));
                    listDTO.add(shopDTO);
                }
                orderDTO.setShop(listDTO);
            }
            getAddressInfo(order, orderDTO);
            list.add(orderDTO);
        }
        result.setData(list);
        return ResModel.success(Code.SUCCESS,result);
    }

    /**
     * 根据id删除订单
     * @param orderId
     * @return
     */
    @Override
    public ResModel deleteByOrderId(Integer orderId) {
        return ResModel.success(Code.DELETE,removeById(orderId));
    }

    /**
     * 根据id集合批量删除
     * @param ids
     * @return
     */
    @Override
    public ResModel batchDelete(List<Integer> ids) {
        return ResModel.success(Code.DELETE,removeByIds(ids));
    }

    /**
     * 下单
     * @param order
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResModel saveOrder(Order order) {
        if (order.getOrderId()!=null){
            String s = redisTemplate.opsForValue().get(ORDER_ID_KEY + order.getOrderId());
            if (StrUtil.isNotEmpty(s)){ //下单成功
                update().setSql("status = 1").last("and order_id = "+StrUtil.toString(s)).update();
                redisTemplate.delete(ORDER_ID_KEY + order.getOrderId());
                String shopIds = order.getShopIds();
                String[] ids = shopIds.split(",");
                for (String id : ids) { //扣库存
                    boolean b = shopClient.reduceStock(Integer.parseInt(id));
                    if (!b){
                        throw new RuntimeException("库存不足");
                    }
                }
                return ResModel.success(Code.SUCCESS,StrUtil.toString(s));
            }else { //订单超时
                LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(true,Order::getOrderId,order.getOrderId());
                remove(wrapper);
            }
        }
        //新下单
        order.setCreateTime(LocalDateTime.now());
        order.setOrderId(NowDateUtils.getOrderId());
        save(order);
        redisTemplate.opsForValue().set(ORDER_ID_KEY+order.getOrderId(), JSON.toJSONString(order.getOrderId()), Duration.ofMinutes(30));
        return ResModel.success(Code.SUCCESS,order.getOrderId());
    }
}
